/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = ora_ttc8_rpc.c                                     */
/*  NOTE      =                                                    */
/*  DATE      = 2014/10/15 by songbb                               */
/*******************************************************************/

#include <stdio.h>
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>

#include "frstr.h"
#include "frmem.h"
#include "frhash2.h"
#include "frcomm.h"
#include "frlog.h"

#include "conntrack.h"
#include "frct_comm.h"

#include "../../ora_core.h"
#include "../../comm/ora_comm.h"
#include "../../comm/ora_util.h"
#include "../ora_mar_engine.h"
#include "../ora_ttc_proto.h"
#include "ora_ttc8_rpc.h"
#include "ora_ttc8_tti_oer.h"
#include "../../comm/ora_stmt.h"

/*******************************************************************************
*  FUNC     :  设置RPC调用函数指针
*  ARGS     :
*  RTN      :
*  NOTE     :
*******************************************************************************/
Ora_rpc_recv* ora_ttc8_rpc_new(void)
{
    Ora_rpc_recv *p_st_ora_rpc_recv = NULL;
    if ((p_st_ora_rpc_recv = (Ora_rpc_recv *) frmalloc(sizeof(Ora_rpc_recv))) == NULL)
    {
        ORA_MALLOCK_ERR;
        return NULL;
    }
    memset(p_st_ora_rpc_recv, 0x00, sizeof(Ora_rpc_recv));

    return p_st_ora_rpc_recv;
}

/*******************************************************************************
*  FUNC     :  解析响应包
*  ARGS     :  *p_st_conn                           (ct信息)
*           :  *p_st_sess                           (Oracle私有的session)
*           :  *p_st_ora_packet                     (Oracle数据包)
*           :  *p_st_hash_report                    (数据上报)
*           :  i_sess_type                          (session类型)
*           :  *p_st_ora_rpc_recv                   (RPC调用函数指针)
*  RTN      :  0                                    (FR_SUCC)
*              1                                    (FR_FAIL)
*  NOTE     :
*******************************************************************************/
int ora_ttc8_rpc_unpack_resp(Conntrack *p_st_conn
                            , L7session_ora *p_st_sess
                            , L7_ora_packet *p_st_ora_packet
                            , Frhash_header *p_st_hash_report
                            , int i_sess_type
                            , Ora_rpc_recv *p_st_ora_rpc_recv)
{
    L7_session *p_st_session = frct_get_session(p_st_conn);
    L7session_ora_private *p_st_session_private = (L7session_ora_private *) frct_get_session_private(p_st_session);
    L7_ora_curr_session *p_st_curr_sess = p_st_session_private->p_st_curr_sess;
    short s_ret_code = 0;                                // return code

    p_st_curr_sess->i_rpa_processed_flag = FR_NO;
    p_st_curr_sess->i_iov_processed_flag = FR_NO;
    p_st_curr_sess->i_cursor_inrpa = 0;

    // 直接设置解析的位置点
    if (p_st_ora_packet->i_analyze_position != 0)
    {
        bytebuff_setPosition(p_st_ora_packet->p_st_packet, p_st_ora_packet->i_analyze_position);
        p_st_curr_sess->i_rpa_processed_flag = p_st_ora_packet->i_rpa_processed_flag;
        p_st_curr_sess->i_iov_processed_flag = p_st_ora_packet->i_iov_processed_flag;
    }

//    ora_report_closed_stmt(p_st_conn, p_st_sess, p_st_ora_packet, p_st_hash_report);

    while (1)
    {
        if (ora_mar_unmarshalUB1(p_st_ora_packet, &s_ret_code) == FR_FAIL)
            goto error;

        switch (s_ret_code)
        {
            case 8:
                ORA_PRINT_INFO("call 8  read_RPA\n");
                if (p_st_ora_rpc_recv->read_RPA == NULL)
                {
                    ORA_PRINT_EMERG("can not find the reference of read_RPA.\n");
                    FRLOG_WARN_DETAIL("can not find the reference of read_RPA.");
                    goto error;
                }
                if (p_st_curr_sess->i_rpa_processed_flag == FR_YES)
                    goto error;
                if (p_st_ora_rpc_recv->read_RPA(p_st_conn, p_st_sess, p_st_ora_packet) != FR_SUCC)
                    goto error;
                p_st_curr_sess->i_rpa_processed_flag = FR_YES;
                break;

            case 21:
                ORA_PRINT_INFO("call 21 read_BVC\n");
                if (p_st_ora_rpc_recv->read_BVC == NULL)
                {
                    ORA_PRINT_EMERG("can not find the reference of read_BVC.\n");
                    FRLOG_WARN_DETAIL("can not find the reference of read_BVC.");
                    goto error;
                }
                if (p_st_ora_rpc_recv->read_BVC(p_st_conn, p_st_sess, p_st_ora_packet) != FR_SUCC)
                    goto error;
                break;

            case 11:
                ORA_PRINT_INFO("call 11 read_IOV\n");
                if (p_st_ora_rpc_recv->read_IOV == NULL)
                {
                    ORA_PRINT_EMERG("can not find the reference of read_IOV.\n");
                    FRLOG_WARN_DETAIL("can not find the reference of read_IOV.");
                    goto error;
                }
                if (p_st_ora_rpc_recv->read_IOV(p_st_conn, p_st_sess, p_st_ora_packet) != FR_SUCC)
                    goto error;
                p_st_curr_sess->i_iov_processed_flag = FR_YES;
                break;

            case 6:
                ORA_PRINT_INFO("call 6  read_RXH\n");
                if (p_st_ora_rpc_recv->read_RXH == NULL)
                {
                    ORA_PRINT_EMERG("can not find the reference of read_RXH.\n");
                    FRLOG_WARN_DETAIL("can not find the reference of read_RXH.");
                    goto error;
                }
                p_st_curr_sess->i_bvc_found = FR_NO;
                p_st_curr_sess->i_bvc_num = 0;
                if (p_st_ora_rpc_recv->read_RXH(p_st_conn, p_st_sess, p_st_ora_packet) != FR_SUCC)
                    goto error;
                break;

            case 12:
                ORA_PRINT_INFO("call 12 process_SLG\n");
                if (p_st_ora_rpc_recv->process_SLG == NULL)
                {
                    ORA_PRINT_EMERG("can not find the reference of process_SLG.\n");
                    FRLOG_WARN_DETAIL("can not find the reference of process_SLG.");
                    goto error;
                }
                break;

            case 7:
                ORA_PRINT_INFO("call 7  read_RXD\n");
                if (p_st_ora_rpc_recv->read_RXD == NULL)
                {
                    ORA_PRINT_EMERG("can not find the reference of read_RXD.\n");
                    FRLOG_WARN_DETAIL("can not find the reference of read_RXD.");
                    goto error;
                }
                if (p_st_ora_rpc_recv->read_RXD(p_st_conn, p_st_sess, p_st_ora_packet) != FR_SUCC)
                    goto error;
                break;

            case 16:
                ORA_PRINT_INFO("call 16 read_DCB\n");
                if (p_st_ora_rpc_recv->read_DCB == NULL)
                {
                    ORA_PRINT_EMERG("can not find the reference of read_DCB.\n");
                    FRLOG_WARN_DETAIL("can not find the reference of read_DCB.");
                    goto error;
                }
                if (p_st_ora_rpc_recv->read_DCB(p_st_conn, p_st_sess, p_st_ora_packet) != FR_SUCC)
                    goto error;
                break;

            case 14:
                ORA_PRINT_INFO("call 14 read_LOBD\n");
                if (p_st_ora_rpc_recv->read_LOBD == NULL)
                {
                    ORA_PRINT_EMERG("can not find the reference of read_LOBD.\n");
                    FRLOG_WARN_DETAIL("can not find the reference of read_LOBD.");
                    goto error;
                }
                if (p_st_ora_rpc_recv->read_LOBD(p_st_conn, p_st_sess, p_st_ora_packet) != FR_SUCC)
                    goto error;
                break;

            case 23:
                // TODO: 这部分代码目前看来不影响主逻辑，暂未做实现
                goto success;

            case 19:
                // this.meg.marshalUB1((short) 19);
                break;

            case 27:
                ORA_PRINT_INFO("call 27 read_IMPLRES\n");
                if (p_st_ora_rpc_recv->read_IMPLRES == NULL)
                {
                    ORA_PRINT_EMERG("can not find the reference of read_IMPLRES.\n");
                    FRLOG_WARN_DETAIL("can not find the reference of read_IMPLRES.");
                    goto error;
                }
                break;

            case 15:
                ORA_PRINT_INFO("call 15 ora_ttc8_tti_oer_unmarshal_warn\n");
                if (ora_ttc8_tti_oer_unmarshal_warn(p_st_conn, p_st_sess, p_st_ora_packet) == FR_FAIL)
                    goto error;
                break;

            case 9:
                ORA_PRINT_INFO("call 9\n");
                bytebuff_setPositionEnd(p_st_ora_packet->p_st_packet);
//                if (!p_st_sess->i_use_special_field && __process_EOCS(p_st_sess, p_st_ora_packet) == FR_FAIL)
//                    goto error;
//
//                // FIXME: 这里c_ttc_version有可能为-1，所以需要判断
//                if ((!p_st_sess->i_use_special_field && p_st_sess->c_ttc_version >= 3 && p_st_sess->s_version_number >= 10000) || (p_st_sess->i_use_special_field && p_st_sess->s_tns_version >= 313))
//                {
//                    if (ora_mar_unmarshalSB2(p_st_sess, p_st_ora_packet, &s_tmp) == FR_FAIL)              // endToEndECIDSequenceNumber
//                        goto error;
//                }
//
//                if (p_st_sess->i_use_special_field && p_st_sess->c_ttc_version >= 2)
//                {
//                    if (ora_mar_skip(p_st_ora_packet, 4) != FR_SUCC)
//                        goto error;
//                }
                goto success;

            case 13:
                ORA_PRINT_INFO("call 13 read_OAC\n");
                if (p_st_ora_rpc_recv->read_OAC == NULL)
                {
                    ORA_PRINT_EMERG("can not find the reference of read_OAC.\n");
                    FRLOG_WARN_DETAIL("can not find the reference of read_OAC.");
                    goto error;
                }
                p_st_ora_rpc_recv->read_OAC(p_st_conn, p_st_sess, p_st_ora_packet);
                break;

            case 4:
                ORA_PRINT_INFO("call 4  oer\n");
                if (ora_ttc8_tti_oer_unmarshal(p_st_conn, p_st_sess, p_st_ora_packet, i_sess_type, p_st_hash_report) == FR_FAIL)
                    goto error;
                goto success;

            default:
                ORA_PRINT_EMERG("unknown returnFlag:[%d]\n", s_ret_code);
                goto error;
        }
    }

success:
    return FR_SUCC;
error:
    return FR_FAIL;
}
